home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
BasicDirectoryModel.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
9KB
|
346 lines
/*
* @(#)BasicDirectoryModel.java 1.6 98/04/14
*
* Copyright (c) 1997,1998 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.basic;
import java.io.File;
import java.util.Vector;
import com.sun.java.swing.*;
import com.sun.java.swing.preview.filechooser.*;
import com.sun.java.swing.preview.*;
import com.sun.java.swing.event.*;
import java.beans.*;
/**
* Basic implementation of a file list.
*
* @version %i% %g%
* @author Jeff Dinkins
*/
class BasicDirectoryModel extends AbstractListModel implements PropertyChangeListener {
private JFileChooser filechooser = null;
private Vector fileCache = null;
private LoadFilesThread loadThread = null;
private Vector files = null;
private Vector directories = null;
BasicDirectoryModel(JFileChooser filechooser) {
this.filechooser = filechooser;
validateFileCache();
}
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if(prop == JFileChooser.DIRECTORY_CHANGED_PROPERTY ||
prop == JFileChooser.FILE_VIEW_CHANGED_PROPERTY ||
prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY ||
prop == JFileChooser.FILE_HIDING_CHANGED_PROPERTY ||
prop == JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY) {
invalidateFileCache();
validateFileCache();
}
}
public void invalidateFileCache() {
files = null;
directories = null;
fileCache = null;
}
public Vector getDirectories() {
if(directories != null) {
return directories;
}
Vector fls = getFiles();
return directories;
}
public Vector getFiles() {
if(files != null) {
return files;
}
files = new Vector();
directories = new Vector();
directories.addElement(filechooser.getFileSystemView().createFileObject(
filechooser.getCurrentDirectory(), "..")
);
for(int i = 0; i < fileCache.size(); i++) {
File f = (File) fileCache.elementAt(i);
if(filechooser.isTraversable(f)) {
directories.addElement(f);
} else {
files.addElement(f);
}
}
return files;
}
public void validateFileCache() {
File currentDirectory = filechooser.getCurrentDirectory();
if(currentDirectory == null) {
invalidateFileCache();
return;
}
// PENDING(jeff) pick the size more sensibly
fileCache = new Vector(50);
// PENDING(jeff) interrupt
if(loadThread != null) {
// interrupt
loadThread.interrupt();
}
loadThread = new LoadFilesThread(currentDirectory);
loadThread.start();
}
// PENDING(jeff) - this is inefficient - should sent out
// incremental adjustment values instead of saying that the
// whole list has changed.
public void fireContentsChanged() {
// System.out.println("BasicDirectoryModel: firecontentschanged");
files = null;
directories = null;
fireContentsChanged(this, 0, fileCache.size()-1);
}
public int getSize() {
if(fileCache != null) {
return fileCache.size();
} else {
return 0;
}
}
public boolean contains(Object o) {
if(fileCache != null) {
return fileCache.contains(o);
} else {
return false;
}
}
public int indexOf(Object o) {
if(fileCache != null) {
return fileCache.indexOf(o);
} else {
return 0;
}
}
public Object getElementAt(int index) {
if(fileCache != null) {
return fileCache.elementAt(index);
} else {
return null;
}
}
// PENDING(jeff) - implement
public void intervalAdded(ListDataEvent e) {
}
// PENDING(jeff) - implement
public void intervalRemoved(ListDataEvent e) {
}
protected void sort(Vector v){
quickSort(v, 0, v.size()-1);
}
// Liberated from the 1.1 SortDemo
//
// This is a generic version of C.A.R Hoare's Quick Sort
// algorithm. This will handle arrays that are already
// sorted, and arrays with duplicate keys.<BR>
//
// If you think of a one dimensional array as going from
// the lowest index on the left to the highest index on the right
// then the parameters to this function are lowest index or
// left and highest index or right. The first time you call
// this function it will be with the parameters 0, a.length - 1.
//
// @param a an integer array
// @param lo0 left boundary of array partition
// @param hi0 right boundary of array partition
private void quickSort(Vector v, int lo0, int hi0) {
int lo = lo0;
int hi = hi0;
File mid;
if (hi0 > lo0) {
// Arbitrarily establishing partition element as the midpoint of
// the array.
mid = (File) v.elementAt((lo0 + hi0) / 2);
// loop through the array until indices cross
while(lo <= hi) {
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
//
// Nasty to have to cast here. Would it be quicker
// to copy the vectors into arrays and sort the arrays?
while((lo < hi0) && lt((File)v.elementAt(lo), mid)) {
++lo;
}
// find an element that is smaller than or equal to
// the partition element starting from the right Index.
while((hi > lo0) && lt(mid, (File)v.elementAt(hi))) {
--hi;
}
// if the indexes have not crossed, swap
if(lo <= hi) {
swap(v, lo, hi);
++lo;
--hi;
}
}
// If the right index has not reached the left side of array
// must now sort the left partition.
if(lo0 < hi) {
quickSort(v, lo0, hi);
}
// If the left index has not reached the right side of array
// must now sort the right partition.
if(lo < hi0) {
quickSort(v, lo, hi0);
}
}
}
private void swap(Vector a, int i, int j) {
Object T = a.elementAt(i);
a.setElementAt(a.elementAt(j), i);
a.setElementAt(T, j);
}
protected boolean lt(File a, File b) {
return a.getName().compareTo(b.getName()) < 0;
}
class LoadFilesThread extends Thread {
File currentDirectory = null;
public LoadFilesThread(File currentDirectory) {
super("Basic L&F File Loading Thread");
this.currentDirectory = currentDirectory;
}
public void run() {
Vector runnables = new Vector(10);
FileSystemView fileSystem = filechooser.getFileSystemView();
File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled());
Vector acceptsList = new Vector();
// run through the file list, add directories and selectable files to fileCache
for (int i = 0; i < list.length; i++) {
if(filechooser.accept(list[i])) {
acceptsList.addElement(list[i]);
}
}
// First sort alphabetically by filename
sort(acceptsList);
Vector directories = new Vector(10);
Vector files = new Vector();
// run through list grabbing directories in chunks of ten
for(int i = 0; i < acceptsList.size(); i++) {
File f = (File) acceptsList.elementAt(i);
boolean isTraversable = filechooser.isTraversable(f);
if(isTraversable) {
directories.addElement(f);
} else if(!isTraversable && filechooser.isFileSelectionEnabled()) {
files.addElement(f);
}
if((directories.size() == 10) || (i == acceptsList.size()-1)) {
DoChangeContents runnable = new DoChangeContents(directories);
runnables.addElement(runnable);
SwingUtilities.invokeLater(runnable);
directories = new Vector(10);
}
if(isInterrupted()) {
// interrupted, cancel all runnables
cancelRunnables(runnables);
return;
}
}
// PENDING(jeff) - run through the files in blocks instead of
// sending them along as one big chunk
DoChangeContents runnable = new DoChangeContents(files);
runnables.addElement(runnable);
SwingUtilities.invokeLater(runnable);
if(isInterrupted()) {
// interrupted, blow out
cancelRunnables(runnables);
return;
}
}
public void cancelRunnables(Vector runnables) {
for(int i = 0; i < runnables.size(); i++) {
((DoChangeContents)runnables.elementAt(i)).cancel();
}
}
}
class DoChangeContents implements Runnable {
private Vector files;
private boolean doFire = true;
private Object lock = new Object();
public DoChangeContents(Vector files) {
this.files = files;
}
synchronized void cancel() {
synchronized(lock) {
doFire = false;
}
}
public void run() {
synchronized(lock) {
if(doFire) {
for(int i = 0; i < files.size(); i++) {
fileCache.addElement(files.elementAt(i));
}
}
fireContentsChanged();
}
}
}
}